/* Copyright 2014 Jan Wolter */

#include "stack.h"
#include <ctype.h>
#include <signal.h>
#include <unistd.h>
#include "game.h"
#include "solve.h"

/* Verbosity:
 *   0: summary output only [-qq]
 *   1: end game and summary [-q]
 *   2: best solution [default]
 *   3: initial state and each move [-v]
 *   4: move options and ratings [-vv]
 *   5: each state [-vvv]
 */

int verbose= 2;

int nstock= 0, nwaste= 0, ntableau= 0, nbouquet= 0, nfound= 0, nbitableau= 0;
int ncourse= 0;
int runcnt= 1;

void runseed(char *seed)
{
    randseed(seed);
    if (verbose > 0) printf("%s - seed %s\n", gamename, seed);
    exec(0,0,0,0);
    fflush(stdout);
}

void usage(char *progname)
{
    printf("Usage: %s [-cfrquv%s] [-a<num>] [-o<num>] <seed> [<cnt>]\n", progname,gameopt);
    exit(1);
}

void hup(int sig)
{
    /* If output is redirected to a file, don't exit on hangups */
    if (isatty(1)) exit(1);
}

int n_opt= 0;	/* Meaning of this depends on the game */

int main (int argc, char **argv)
{
    char *seed= NULL;
    char *cnt= NULL;
    int arif= 0;	/* Do an a-shuffle */
    int over= 0;	/* Do this many overhand shuffles */
    int cut= 1;		/* Do this many cuts */
    int fresh= 0;

    signal(SIGHUP, hup);

    for (int i= 1; i < argc; i++)
    {
	if (argv[i][0] == '-')
	{
	    for (int j= 1; j < strlen(argv[i]); j++)
	    {
		switch (argv[i][j])
		{
		    case 'q': verbose--; break;
		    case 'v': verbose++; break;
		    case 'f': fresh= 1; break;
		    case 'r': fresh= 2; break;
		    case 'c': cut= 0; break;
		    case 'u': unixrand= 1; break;
		    case 'a': while isdigit(argv[i][j+1])
				  arif= arif*10 + (argv[i][++j]-'0');
			      break;
		    case 'o': while isdigit(argv[i][j+1])
				  over= over*10 + (argv[i][++j]-'0');
			      break;
		    case 'n': while isdigit(argv[i][j+1])
				  n_opt= n_opt*10 + (argv[i][++j]-'0');
			      break;
		    default: 
			  if (index(gameopt, argv[i][j]))
			      setopt(argv[i][j]);
			  else
			      usage(argv[0]);
		}
	    }
	}
	else if (seed == NULL)
	    seed= argv[i];
	else if (cnt == NULL)
	    cnt= argv[i];
    }
    if (arif == 0 && over == 0) fresh= 0;
    if (seed == NULL || arif == 1 || (arif > 0 && !fresh && cnt == NULL))
	usage(argv[0]);

#ifdef MTRACE
    mtrace();
#endif

    int nseed= atoi(seed);
    int ncnt= (cnt == NULL) ? 1 : atoi(cnt);
    int maxseed= nseed+ncnt-1;

    if (fresh)
    {
	for (int s= nseed; s <= maxseed; s++)
	{
	    char buf[50];
	    sprintf(buf,"%d",s);
	    randseed(buf);
	    if (verbose > 0) printf("%s - seed %s\n", gamename, buf);
	    if (gathered != NULL) freeStack(gathered);
	    if (fresh == 2)
		gathered= sorted();
	    else
		gathered= revsorted();
/*printStack(stdout,"Sorted",gathered);*/
	    exec(0,arif,over,cut);
	    fflush(stdout);
	    runcnt++;
	}
	summary();
    }
    else if (arif > 0 || over > 0)
    {
	randseed(seed);
	if (verbose > 0) printf("%s - seed %s\n", gamename, seed);
	exec(1,0,0,0);
	fflush(stdout);
	for (int i= 1; i < ncnt; i++)
	{
	    if (verbose > 0)
		printf("%s - Deal %d (a=%d, nover=%d, cut=%d)\n",
		    gamename, i, arif, over, cut);
/*if (i > 0) printStack(stdout,"Gathered",gathered);*/
	    exec(1,arif,over,cut);
	    fflush(stdout);
	    runcnt++;
	}
	summary();
    }
    else
    {
	for (int s= nseed; s <= maxseed; s++)
	{
	    char buf[50];
	    sprintf(buf,"%d",s);
	    runseed(buf);
	    runcnt++;
	}
	if (ncnt > 1) summary();
    }

#ifdef MTRACE
    muntrace();
#endif
}

Stack *tmpstack= NULL;

Stack *mixcards(int arif, int over, int cut)
{
    Stack *shuf, *spare, *tmp;

    if (gathered != NULL && (arif > 1 || over > 0))
    {
	/* Shuffle a previously gathered deck */

	cleanDeck();
	
	tmpstack= allocStack(ncard);

	shuf= gathered;	/* Pointer to the active deck */
	spare= tmpstack; /* extra memory space */

	if (over > 0)
	{
	    overhand(shuf, spare, 4, over);
	    tmp= shuf; shuf= spare; spare= tmp;
	}

	if (arif > 1)
	{
	    riffle(shuf, spare, arif);
	    tmp= shuf; shuf= spare; spare= tmp;
	}

	if (cut > 0)
	{
	    cutdeck(shuf, spare);
	    tmp= shuf; shuf= spare; spare= tmp;
	}
	gathered= spare;
	return shuf;
    }
    else
	/* Fully randomized deck */
	return shuffle();
}
